package com.alipay.rebate.shop.configuration.shiro;

import com.alipay.rebate.shop.configuration.shiro.realm.*;
import com.alipay.rebate.shop.filter.shiro.JwtAdminAuthFilter;
import com.alipay.rebate.shop.filter.shiro.JwtCustomerAuthFilter;
import com.alipay.rebate.shop.filter.shiro.RolesAuthorizationFilter;
import com.alipay.rebate.shop.service.admin.AdminUserService;
import com.alipay.rebate.shop.service.common.UserService;
import com.alipay.rebate.shop.service.admin.AdminCustomerUserService;
import com.alipay.rebate.shop.service.customer.CustomerUserService;
import org.apache.shiro.authc.Authenticator;
import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.springframework.data.redis.core.StringRedisTemplate;

/**
 * shiro配置类
 */
@Configuration
public class ShiroConfiguration {

    @Bean
    public FilterRegistrationBean filterRegistrationBean(
        SecurityManager securityManager,
        CustomerUserService customerUserService,
        AdminCustomerUserService adminUserService
        ) throws Exception{
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter((Filter)shiroFilter(securityManager, customerUserService,adminUserService).getObject());
        filterRegistration.addInitParameter("targetFilterLifecycle", "true");
        filterRegistration.setAsyncSupported(true);
        filterRegistration.setEnabled(true);
        filterRegistration.setDispatcherTypes(DispatcherType.REQUEST,DispatcherType.ASYNC);

        return filterRegistration;
    }

    @Bean
    public Authenticator authenticator() {
        ModularRealmAuthenticator authenticator = new CustomRealmAuthenticator();
        authenticator.setAuthenticationStrategy(new FirstSuccessfulStrategy());
        return authenticator;
    }

    @Bean("dbRealm")
    public Realm dbShiroRealm(CustomerUserService userService) {
        PhoneShiroRealm myShiroRealm = new PhoneShiroRealm(userService);
        return myShiroRealm;
    }

    @Bean("jwtRealm")
    public Realm jwtShiroRealm(CustomerUserService userService) {
        JWTShiroRealm myShiroRealm = new JWTShiroRealm(userService);
        return myShiroRealm;
    }

    @Bean("weixinRealm")
    public Realm weixinShiroRealm(CustomerUserService userService) {
        WeixinShiroRealm weixinShiroRealm = new WeixinShiroRealm(userService);
        return weixinShiroRealm;
    }

    @Bean("userNamePasswordRealm")
    public Realm userNamePasswordRealm(CustomerUserService userService) {
        UserNamePasswordRealm userNamePasswordRealm = new UserNamePasswordRealm(userService);
        return userNamePasswordRealm;
    }

    @Bean("adminRealm")
    public Realm adminRealm(AdminUserService userService) {
        AdminShiroRealm adminShiroRealm = new AdminShiroRealm(userService);
        return adminShiroRealm;
    }

    /**
     * 设置过滤器
     */
    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(
        SecurityManager securityManager,
        CustomerUserService customerUserService,
        AdminCustomerUserService adminUserService
        ) {
    	ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(securityManager);
        Map<String, Filter> filterMap = factoryBean.getFilters();
        // 客户端过滤器
        filterMap.put("authcToken", createCustomerAuthFilter(customerUserService));
        // pc后台过滤器
        filterMap.put("adminAuthcToken",createAdminAuthFilter(adminUserService));
        filterMap.put("anyRole", createRolesFilter());
        factoryBean.setFilters(filterMap);

        Map<String,String> shiroFilterChainDefinitions = new HashMap<>();
//        shiroFilterChainDefinitions.put("/common/login", "noSessionCreation,anon");
//        shiroFilterChainDefinitions.put("/common/adminLogin", "noSessionCreation,anon");

        shiroFilterChainDefinitions.put("/customer/register", "noSessionCreation,anon");
        shiroFilterChainDefinitions.put("/customer/selectIndexPageFrameWork", "noSessionCreation,anon");
//        shiroFilterChainDefinitions.put("/customer/selectPageFrameWork", "noSessionCreation,anon");
        shiroFilterChainDefinitions.put("/customer/findPassword", "noSessionCreation,anon");
//        shiroFilterChainDefinitions.put("/product/*", "noSessionCreation,anon");
        shiroFilterChainDefinitions.put("/common/**", "noSessionCreation,anon");
        shiroFilterChainDefinitions.put("/customer/entity/settings/**", "noSessionCreation,anon");
//        shiroFilterChainDefinitions.put("/logoff", "noSessionCreation,authcToken[permissive]");
        shiroFilterChainDefinitions.put("/image/**", "anon");
        shiroFilterChainDefinitions.put("/admin/**", "noSessionCreation,adminAuthcToken"); //只允许admin或manager角色的用户访问
        shiroFilterChainDefinitions.put("/article/list", "noSessionCreation,authcToken");
        shiroFilterChainDefinitions.put("/article/*", "noSessionCreation,authcToken[permissive]");
        shiroFilterChainDefinitions.put("/**", "noSessionCreation,authcToken");
        factoryBean.setFilterChainDefinitionMap(shiroFilterChainDefinitions);

        return factoryBean;
    }

    @Bean("securityManager")
    public DefaultWebSecurityManager getManager(
        AdminUserService adminUserService,
        CustomerUserService customerUserService,
        Authenticator authenticator
        ) {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        // 使用自己的realm
        manager.setAuthenticator(authenticator);
        manager.setRealms(Arrays.asList(
                jwtShiroRealm(customerUserService),
                dbShiroRealm(customerUserService),
                weixinShiroRealm(customerUserService),
                userNamePasswordRealm(customerUserService),
                adminRealm(adminUserService)
                )
        );
        /*
         * 关闭shiro自带的session，详情见文档
         * http://shiro.apache.org/session-management.html#SessionManagement-StatelessApplications%28Sessionless%29
         */
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        manager.setSubjectDAO(subjectDAO);

        return manager;
    }


    private JwtAdminAuthFilter createAdminAuthFilter(UserService userService){
        return new JwtAdminAuthFilter(userService);
    }

    private JwtCustomerAuthFilter createCustomerAuthFilter(UserService userService){
        return new JwtCustomerAuthFilter(userService);
    }


    private RolesAuthorizationFilter createRolesFilter(){
        return new RolesAuthorizationFilter();
    }

}
